package lk.icta.core.service.impl;

import lk.icta.common.ELandRuntimeException;
import lk.icta.common.ErrorCodes;
import lk.icta.common.dao.impl.BaseDAO;
import lk.icta.core.dao.OrganizationDAO;
import lk.icta.core.entity.Organization;
import lk.icta.core.service.OrganisationManagementService;
import lk.icta.user.common.Permission;
import lk.icta.user.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * @author Tharanga Punchihewa
 */
public class OrganisationManagementServiceImpl extends BaseDAO implements OrganisationManagementService {

    private static final Logger logger = LoggerFactory.getLogger(OrganisationManagementServiceImpl.class);
    private OrganizationDAO organizationDAO;

    public OrganisationManagementServiceImpl(OrganizationDAO organizationDAO) {
        this.organizationDAO = organizationDAO;
    }


    @Transactional(propagation = Propagation.REQUIRED)
    public void addOrganization(Organization organization, User user) {
        if (user.isAuthorized(Permission.MANAGE_GOVERNMENT_ORGANIZATION)) {
            organization.setStatus(Organization.State.ACTIVE);
            organizationDAO.addOrganization(organization, user);
            logger.debug("Added {} organization ,idUKey of the organization is : {}", organization.getOrganizationNameEn(), organization.getId());
        } else {
            logger.debug("No permission");
            handleELandRuntimeException(user.getUsername() + " doesn't have permission to add organization", ErrorCodes.UNAUTHORIZED_ACCESS);
        }
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void updateOrganization(Organization organization, User user) {
        if (user.isAuthorized(Permission.MANAGE_GOVERNMENT_ORGANIZATION)) {
            organization.setStatus(Organization.State.ACTIVE);
            organizationDAO.updateOrganization(organization, user);
            logger.debug("updated  {} organization ,idUKey of the organization is : {}", organization.getOrganizationNameEn(), organization.getId());
        } else {
            logger.debug("No permission");
            handleELandRuntimeException(user.getUsername() + " doesn't have permission to update organization", ErrorCodes.UNAUTHORIZED_ACCESS);
        }
    }
    //Update due Date

    @Transactional(propagation = Propagation.REQUIRED)
    public void updateDueDate(Organization organization, User user) {
        if (user.isAuthorized(Permission.MANAGE_GOVERNMENT_ORGANIZATION)) {
            if (organization.getId() != 0) {
                //organization.setStatus(Organization.State.LETTER_GENERATED);
                organization.setStatus(Organization.State.ACTIVE);
                organizationDAO.updateDueDate(organization, user);
                logger.debug("updated  {} organization due date ,idUKey of the organization is : {}", organization.getId());

            } else {
                logger.debug("Invalid organization Id");
                handleELandRuntimeException(user.getUsername() + " Invalid organization Id", ErrorCodes.UNAUTHORIZED_ACCESS);

            }

        } else {
            logger.debug("No permission");
            handleELandRuntimeException(user.getUsername() + " doesn't have permission to update organization", ErrorCodes.UNAUTHORIZED_ACCESS);
        }
    }


    @Transactional(propagation = Propagation.REQUIRED)
    public Organization getOrganizationByIdUKey(int id, User user) {
        logger.debug("get organization by idUKey : {}", id);
        return organizationDAO.getOrganizationByIdUKey(id, user);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public List<Organization> getAllOrganizations(User user) {
        if (user.isAuthorized(Permission.MANAGE_GOVERNMENT_ORGANIZATION)) {
            logger.debug("Populate all Organization list by :", user.getUsername());
            return organizationDAO.getAllOrganizations(user);
        } else {
            logger.debug("No permission");
            handleELandRuntimeException(user.getUsername() + " doesn't have permission to get organization List", ErrorCodes.UNAUTHORIZED_ACCESS);
        }
        return null;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void inactiveOrganization(Organization organization, User user) {
        organization.setStatus(Organization.State.INACTIVE);
        organizationDAO.updateOrganization(organization, user);
        logger.debug("Inactive organization id is : {}", organization.getId());
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public Map<Integer, String> getOrganizationListByLanguage(String language, User user) {
        logger.debug("Request Organization list by : {}", user.getUsername());
        return organizationDAO.getOrganizationListByLanguage(language);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public List<Organization> getUnRegisterOrganizationList(User user) {
        logger.debug("Request Un Organization list by : {}", user.getUsername());
        return organizationDAO.getOrganizationListByType(Organization.Type.UN_REGISTERED, user);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public List<Organization> getActiveOrganizationList(User user) {
        logger.debug("Request Active  Organization list by : {}", user.getUsername());
        return organizationDAO.getOrganizationListByState(Organization.State.ACTIVE);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public List<Organization> getRegisterOrganizationList(User user) {
        logger.debug("Request Un Organization list by : {}", user.getUsername());
        return organizationDAO.getOrganizationListByType(Organization.Type.REGISTERED, user);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public List<Organization> getActiveUnRegisterOrganizationList(User user) {
        logger.debug("Request Active Un-Registered Organization list by : {}", user.getUsername());
        return organizationDAO.getOrganizationListByStateAndType(Organization.State.ACTIVE, Organization.Type.UN_REGISTERED, user);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public List<Organization> getActiveRegisterOrganizationList(User user) {
        logger.debug("Request Active Registered Organization list by : {}", user.getUsername());
        return organizationDAO.getOrganizationListByStateAndType(Organization.State.ACTIVE, Organization.Type.REGISTERED, user);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public List<Organization> getInitInfoOrganizationList(User user) {
        logger.debug("Request Un Organization list by : {}", user.getUsername());
        return organizationDAO.getOrganizationListByType(Organization.Type.INITIAL_DATA_ENTRY, user);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void activeOrganization(Organization organization, User user) {
        organization.setStatus(Organization.State.ACTIVE);
        organizationDAO.updateOrganization(organization, user);
        logger.debug("Active organization id is : {}", organization.getId());
    }

    private void handleELandRuntimeException(String message, int code) {
        logger.error(message);
        throw new ELandRuntimeException(message, code);
    }
}
